/**
 *AUTHOR:第七页(diqye) 2014年8月27日,  13:13:46 QQ:262666212
 *定时器是根据PhysicsJs的定时器而改造的
 * The Ticker singleton for easily binding callbacks to requestAnimationFrame
 */
(function(diqye,factory){
	if (typeof exports === 'object') {
        // Node. 
        module.exports = factory.call(diqye);
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(function(){ return factory.call(diqye) });
    } else {
        // Browser globals (diqye is window)
        window.ticker = factory.call(diqye);
    }
}(this,function(){
    window = this;
    var  lastTime = 0
        ,active = false
        ,listeners = []
        ;

    /**
     * Publish a tick to subscribed callbacks
     * @private
     * @param  {Number} time The current time
     * @return {void}
     */
    function step( time ){

        var fns = listeners,rval,unFns=[];
        if(listeners.length==0){
        	stop();
        }
        if (!active){
            return;
        }
        if(window.requestAnimationFrame){
        	window.requestAnimationFrame( function(){
        		step(new Date().getTime());
        	});
        }else{
        	setTimeout(function(){
        		step(new Date().getTime());
        	},20);
        }
        
        for ( var i = 0,l=fns.length; i < l; ++i ){
            
            rval=fns[ i ]( time, time - lastTime );
            if("END" == rval)unFns.push(fns[i]);
        }
        if(unFns.length!=0)unsubscribe(unFns);

        lastTime = time;
    }

    /**
     * Start the ticker
     * @return {this}
     */
    function start(){
        
        lastTime = (new Date()).getTime();
        active = true;
        step(lastTime);

        return this;
    }

    /**
     * Stop the ticker
     * @return {this}
     */
    function stop(){

        active = false;
        return this;
    }

    /**
     * Subscribe a callback to the ticker
     * @param  {Function} listener The callback function
     * @return {this}
     */
    function subscribe( listener ){

        // if function and not already in listeners...
        if ( typeof listener === 'function' ){

            for ( var i = 0, l = listeners.length; i < l; ++i ){
                
                if (listener === listeners[ i ]){
                    return this;
                }
            }

            // add it
            listeners.push( listener );
        }
        
        return this;
    }

    /**
     * Unsubscribe a callback from the ticker
     * @param  {Function} listener Original callback added
     * @return {this}
     */
    function unsubscribe( listener ){
    	if(listener instanceof Array){
    		for(var i=0,l=listener.length;i<l;i++){
    			unsubscribe(listener[i]);
    		}
    	}
        var fns = listeners;

        for ( var i = 0, l = fns.length; i < l; ++i ){
            
            if ( fns[ i ] === listener ){

                // remove it
                fns.splice( i, 1 );
                return this;
            }
        }

        return this;
    }

    /**
     * Determine if ticker is currently running
     * @return {Boolean} True if running
     */
    function isActive(){

        return !!active;
    }

    // API
   return {
        start: start,
        stop: stop,
        subscribe: subscribe,
        unsubscribe: unsubscribe,
        isActive: isActive
    };

}));